#include "../inc/Circle.h"
#include "../inc/tools.h"
#include <iostream>

using namespace std;


Circle::Circle (void)
{
    id = Circle::next_id++ ;
    A = 0;
    B = 0;
    C = 0;
    R = 0;
    normal.Import(vcg::Point3f(0,0,0)) ;
    score = 0 ;
    R_before = 0 ;
    res.SetZero();
    range=0;
}               

Circle::Circle(float _a, float _b, float _r )
{
    id = Circle::next_id++ ;
    A = _a;
    B = _b;
    C = 0;
    R = _r;
    score = 0 ;
    R_before = 0 ;
    res.SetZero();
    range=0.;
    var= 0.;
    nbPt = 0;

}

Circle::Circle(float _a, float _b, float _c, float _r )
{
    id = Circle::next_id++ ;
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = 0 ;
    R_before = 0 ;
    res.SetZero();
    range=0.;
    var= 0.;
    nbPt = 0;
}

Circle::Circle(float _a, float _b, float _c, float _r, int _s )
{
    id = Circle::next_id++ ;
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = _s ;
    R_before = 0 ;
    res.SetZero();
    range=0.;
    var= 0.;
    nbPt = 0;
}

/*Circle::Circle(float _a, float _b, float _c, float _r, int _s, vcg::Point4f _res )
{
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = _s ;
    R_before = 0 ;
    res = _res ;
}

Circle::Circle(float _a, float _b, float _c, float _r, int _s , float v, int n)
{
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = _s ;
    var= v;
    nbPt = n;
    R_before = 0 ;
    res.SetZero();
}

Circle::Circle(float _a, float _b, float _c, float _r, int _s , float v, int n, vcg::Point4f _res)
{
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = _s ;
    var= v;
    nbPt = n;
    R_before = 0 ;
    res = _res ;
}*/

Circle::Circle(float _a, float _b, float _c, float _r, int _s , float v, int n, float _range, vcg::Point4f _res)
{
    id = Circle::next_id++ ;
    A = _a;
    B = _b;
    C = _c;
    R = _r;
    score = _s ;
    var= v;
    nbPt = n;
    R_before = 0 ;
    res = _res ;
    range = _range;
}

Circle::Circle(CVertexO _p1, CVertexO _p2, CVertexO _p3 )
{
    id = Circle::next_id++ ;
    /* Cf graphics gems Book 1 page 21 */
    CVertexO p31, p21, p32, p12, p13, p23;
    float d1, d2, d3, c1, c2, c3, c;

    p31.P() = diffPoint( _p3, _p1 ).P();
    p21.P() = diffPoint( _p2, _p1 ).P();
    p32.P() = diffPoint( _p3, _p2 ).P();
    p12.P() = diffPoint( _p1, _p2 ).P();
    p13.P() = diffPoint( _p1, _p3 ).P();
    p23.P() = diffPoint( _p2, _p3 ).P();

    d1 = scalarProduct2D( p31, p21 );
    d2 = scalarProduct2D( p32, p12 );
    d3 = scalarProduct2D( p13, p23 );

    c1 = d2*d3;
    c2 = d3*d1;
    c3 = d1*d2;
    c = c1 + c2 + c3;

    R = 0.5*sqrt(((d1+d2)*(d2+d3)*(d3+d1))/c);
    A = (((c2 + c3)*_p1.P()[0]) + ((c3+c1)*_p2.P()[0]) + ((c1+c2)*_p3.P()[0]))/(2*c);
    B = (((c2 + c3)*_p1.P()[1]) + ((c3+c1)*_p2.P()[1]) + ((c1+c2)*_p3.P()[1]))/(2*c);
    C = 0;
    score = 0 ;
    R_before = 0 ;
}

Circle::Circle(const Circle & _c)
{
    this->id = _c.id ;
    this->A = _c.A;
    this->B = _c.B;
    this->C = _c.C;
    this->R = _c.R;
    this->normal = _c.normal;
    this->score = _c.score ;
    this->R_before = _c.R_before ;
    this->res = _c.res ;
    this->var = _c.var ;
    this->nbPt = _c.nbPt ;
    this->range = _c.range ;
}

Circle::~Circle(){}

void Circle::setABR(float _a, float _b, float _r)
{
    this->A = _a;
    this->B = _b;
    this->C = 0;
    this->R = _r;
}

void Circle::setABCR(float _a, float _b, float _c, float _r)
{
    this->A = _a;
    this->B = _b;
    this->C = _c;
    this->R = _r;
}

void Circle::draw( float _z )
{
    int sections = 40; /* Nombre de sections utilises pour dessiner le cercle */
    float twoPi = 2.0f * 3.14159f;

    glColor3f(1,0,0);
    glBegin(GL_LINE_LOOP);
    for(int i = 0; i <= sections;i++)
    {
        glVertex3f(this->getR() * cos(i *  twoPi / sections) + this->getA(), this->getR() * sin(i * twoPi / sections)  + this->getB(), _z );
    }
    glEnd();
    glColor3f(1,1,1);
}

void Circle::draw(float _z, float _r, float _g, float _b)
{
    int sections = 40; /* Nombre de sections utilises pour dessiner le cercle */
    float twoPi = 2.0f * 3.14159f;

    glColor3f(_r,_g,_b);
    glBegin(GL_LINE_LOOP);
    for(int i = 0; i <= sections;i++)
    {
        glVertex3f(this->getR() * cos(i *  twoPi / sections) + this->getA(), this->getR() * sin(i * twoPi / sections)  + this->getB(), _z );
    }
    glEnd();
    glColor3f(1,1,1);
}

void Circle::print()
{
    cout<<"Cercle de centre ( "<<A<<", "<<B<<", "<<C<<" ) et de rayon "<<R<<endl;
}

bool Circle::intersect(Circle _c)
{
    float dist = this->getR() + _c.getR();
    return (sqrt(pow(this->getA()-_c.getA(), 2) + pow(this->getB()-_c.getB(), 2)) < dist);
}

int Circle::conflict(Circle _c)
{
    float dist = sqrt(pow(this->getA()-_c.getA(), 2) + pow(this->getB()-_c.getB(), 2));
    float sum = this->getR() + _c.getR();

    if ( dist < sum )
    {
        if ( dist + _c.getR() < this->getR() || dist + this->getR() < _c.getR() )
            return 0;

        return 1;
    }

    return -1;
}

